package cn.com.fattiger.framework.remoting.netty4.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.ThreadFactory;

import cn.com.fattiger.framework.remoting.netty4.server.coder.Decoder;
import cn.com.fattiger.framework.remoting.netty4.server.coder.Encoder;
import cn.com.fattiger.framework.remoting.server.AbstractServer;
import cn.com.fattiger.framework.remoting.thread.NamedThreadFactory;


public class Netty4Server extends AbstractServer {

	private static final int PROCESSORS = Runtime.getRuntime().availableProcessors() * 2;
	private EventLoopGroup bossGroup    = null;
	private EventLoopGroup workerGroup  = null;
	
	private int port = 8888;
	private String hostName;
	public Netty4Server(int port){
		this(null, port);
	}
	
	public Netty4Server(String hostName, int port){
		this.hostName = hostName;
		this.port = port;
	}
	
	@Override
	public void start() throws Exception {
		ThreadFactory bossThread =  new NamedThreadFactory("NETTY4-BOSS-");
		ThreadFactory workerThread =  new NamedThreadFactory("NETTY4-WORKER-");
		bossGroup = new NioEventLoopGroup(PROCESSORS, bossThread);//无参构造函数 可用内核数*2
		workerGroup = new NioEventLoopGroup(PROCESSORS * 2, workerThread);
		//3和4的区别 4采用构建模式编码风格
		ServerBootstrap server = new ServerBootstrap();
		server.group(bossGroup, workerGroup)
		.channel(NioServerSocketChannel.class)
		.option(ChannelOption.SO_KEEPALIVE, true)
		.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60 * 1000)
		.option(ChannelOption.SO_BACKLOG, 128)
		.option(ChannelOption.SO_RCVBUF, 65535)
		.option(ChannelOption.SO_SNDBUF, 65535)
		.childOption(ChannelOption.TCP_NODELAY, true)
		.childOption(ChannelOption.SO_REUSEADDR, true)
		.childOption(ChannelOption.SO_RCVBUF, 65535)
		.childOption(ChannelOption.SO_SNDBUF, 65535);
		server.childHandler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel channel) throws Exception {
				  ChannelPipeline pipeline = channel.pipeline();
				  pipeline.addLast("decode", new Decoder());
				  pipeline.addLast("encode", new Encoder());
				  
			}});
	}

	@Override
	public void stop() {
		bossGroup.shutdownGracefully();
		workerGroup.shutdownGracefully();
	}

}
